"""
数据源路由器

核心路由器，负责协调所有路由策略，选择最优数据源适配器。

主要功能：
1. 管理多个路由策略
2. 协调适配器注册和发现
3. 执行路由决策
4. 故障转移和降级
5. 性能监控和统计

作者: RedFire Team
创建日期: 2025-10-06
版本: v1.0
"""

from typing import Dict, List, Optional, Any
import logging
from datetime import datetime

from app.adapters.base import BaseMarketDataAdapter
from app.routing.strategy import (
    RoutingStrategy,
    RoutingContext,
    RoutingResult,
    CompositeRoutingStrategy,
    create_routing_context
)
from app.routing.registry import CapabilityRegistry


class DataSourceRouter:
    """
    数据源路由器
    
    核心路由组件，负责：
    1. 管理适配器注册
    2. 管理路由策略
    3. 执行路由决策
    4. 故障处理和转移
    
    使用示例：
    ```python
    router = DataSourceRouter()
    
    # 注册适配器
    router.register_adapter(tushare_adapter)
    router.register_adapter(akshare_adapter)
    
    # 添加路由策略
    router.add_strategy(priority_strategy)
    router.add_strategy(capability_strategy)
    
    # 执行路由
    context = create_routing_context("get_quote", symbols=["000001.SZ"])
    result = await router.route(context)
    
    # 获取适配器实例
    adapter = router.get_adapter(result.primary_adapter)
    ```
    """
    
    def __init__(
        self,
        enable_auto_failover: bool = True,
        max_failover_attempts: int = 3,
        logger: Optional[logging.Logger] = None
    ):
        """
        初始化数据源路由器
        
        Args:
            enable_auto_failover: 是否启用自动故障转移
            max_failover_attempts: 最大故障转移尝试次数
            logger: 日志记录器
        """
        self.logger = logger or logging.getLogger(__name__)
        self.enable_auto_failover = enable_auto_failover
        self.max_failover_attempts = max_failover_attempts
        
        # 能力注册表
        self.registry = CapabilityRegistry(logger=self.logger)
        
        # 路由策略（使用组合策略模式）
        self.strategy = CompositeRoutingStrategy(logger=self.logger)
        
        # 路由统计
        self.routing_stats: Dict[str, int] = {}
        self.failure_stats: Dict[str, int] = {}
        
        # 初始化时间
        self.initialized_at = datetime.now()
        
        self.logger.info(
            f"数据源路由器初始化: "
            f"自动故障转移={enable_auto_failover}, "
            f"最大重试={max_failover_attempts}"
        )
    
    def register_adapter(
        self,
        adapter: BaseMarketDataAdapter,
        override: bool = False
    ) -> bool:
        """
        注册数据源适配器
        
        Args:
            adapter: 适配器实例
            override: 是否覆盖已存在的注册
        
        Returns:
            bool: 是否注册成功
        """
        success = self.registry.register_adapter(adapter, override)
        if success:
            self.routing_stats[adapter.provider_name] = 0
            self.failure_stats[adapter.provider_name] = 0
            self.logger.info(f"适配器注册成功: {adapter.provider_name}")
        return success
    
    def unregister_adapter(self, adapter_name: str) -> bool:
        """
        注销数据源适配器
        
        Args:
            adapter_name: 适配器名称
        
        Returns:
            bool: 是否注销成功
        """
        success = self.registry.unregister_adapter(adapter_name)
        if success:
            self.routing_stats.pop(adapter_name, None)
            self.failure_stats.pop(adapter_name, None)
            self.logger.info(f"适配器注销成功: {adapter_name}")
        return success
    
    def add_strategy(self, strategy: RoutingStrategy):
        """
        添加路由策略
        
        Args:
            strategy: 路由策略
        """
        self.strategy.add_strategy(strategy)
        self.logger.info(f"添加路由策略: {strategy.name}")
    
    def remove_strategy(self, strategy_name: str) -> bool:
        """
        移除路由策略
        
        Args:
            strategy_name: 策略名称
        
        Returns:
            bool: 是否移除成功
        """
        success = self.strategy.remove_strategy(strategy_name)
        if success:
            self.logger.info(f"移除路由策略: {strategy_name}")
        return success
    
    async def route(self, context: RoutingContext) -> RoutingResult:
        """
        执行路由决策
        
        Args:
            context: 路由上下文
        
        Returns:
            RoutingResult: 路由结果
        """
        start_time = datetime.now()
        
        try:
            # 获取可用的适配器列表
            available_adapters = self.registry.get_all_adapter_names(only_healthy=True)
            
            if not available_adapters:
                self.logger.error("没有可用的健康适配器")
                return RoutingResult(
                    routing_reason="没有可用的健康适配器",
                    confidence_score=0.0
                )
            
            # 执行路由策略
            result = await self.strategy.select_adapter(context, available_adapters)
            
            # 更新统计
            if result.is_valid():
                self.routing_stats[result.primary_adapter] = \
                    self.routing_stats.get(result.primary_adapter, 0) + 1
            
            # 记录路由时间
            elapsed = (datetime.now() - start_time).total_seconds()
            result.metadata["routing_time_ms"] = elapsed * 1000
            
            self.logger.info(
                f"路由完成: {context.request_type} -> {result.primary_adapter} "
                f"(耗时: {elapsed*1000:.2f}ms, 置信度: {result.confidence_score:.2f})"
            )
            
            return result
            
        except Exception as e:
            self.logger.error(f"路由失败: {e}", exc_info=True)
            return RoutingResult(
                routing_reason=f"路由执行异常: {str(e)}",
                confidence_score=0.0
            )
    
    async def route_with_execution(
        self,
        context: RoutingContext,
        execution_func: callable,
        *args,
        **kwargs
    ) -> Any:
        """
        路由并执行请求（带自动故障转移）
        
        Args:
            context: 路由上下文
            execution_func: 执行函数（接受adapter作为第一个参数）
            *args: 执行函数的其他参数
            **kwargs: 执行函数的关键字参数
        
        Returns:
            Any: 执行结果
        
        Raises:
            RuntimeError: 所有适配器都失败时抛出
        """
        # 执行路由
        result = await self.route(context)
        
        if not result.is_valid():
            raise RuntimeError("路由失败，没有可用的适配器")
        
        # 获取所有候选适配器（主 + 备选）
        candidate_adapters = result.get_all_adapters()
        
        # 尝试执行
        last_error = None
        attempts = 0
        
        for adapter_name in candidate_adapters:
            if attempts >= self.max_failover_attempts:
                self.logger.warning(f"达到最大故障转移次数: {self.max_failover_attempts}")
                break
            
            attempts += 1
            adapter = self.get_adapter(adapter_name)
            
            if not adapter:
                self.logger.warning(f"适配器实例不存在: {adapter_name}")
                continue
            
            try:
                self.logger.info(f"尝试使用适配器: {adapter_name} (第 {attempts} 次尝试)")
                
                # 执行请求
                result_data = await execution_func(adapter, *args, **kwargs)
                
                # 成功！
                self.logger.info(f"请求执行成功: {adapter_name}")
                return result_data
                
            except Exception as e:
                last_error = e
                self.logger.error(f"适配器 {adapter_name} 执行失败: {e}")
                
                # 更新失败统计
                self.failure_stats[adapter_name] = \
                    self.failure_stats.get(adapter_name, 0) + 1
                
                # 标记为不健康（如果失败次数过多）
                if self.failure_stats[adapter_name] >= 5:
                    self.registry.set_adapter_health(adapter_name, False)
                    self.logger.warning(f"适配器 {adapter_name} 标记为不健康")
                
                # 如果禁用了自动故障转移，直接抛出异常
                if not self.enable_auto_failover:
                    raise
                
                # 继续尝试下一个适配器
                continue
        
        # 所有适配器都失败
        error_msg = f"所有适配器都失败，尝试次数: {attempts}"
        self.logger.error(error_msg)
        if last_error:
            raise RuntimeError(error_msg) from last_error
        else:
            raise RuntimeError(error_msg)
    
    def get_adapter(self, adapter_name: str) -> Optional[BaseMarketDataAdapter]:
        """
        获取适配器实例
        
        Args:
            adapter_name: 适配器名称
        
        Returns:
            Optional[BaseMarketDataAdapter]: 适配器实例
        """
        return self.registry.get_adapter_instance(adapter_name)
    
    def get_all_adapters(self, only_healthy: bool = False) -> List[str]:
        """
        获取所有适配器名称
        
        Args:
            only_healthy: 是否只返回健康的适配器
        
        Returns:
            List[str]: 适配器名称列表
        """
        return self.registry.get_all_adapter_names(only_healthy)
    
    def set_adapter_health(self, adapter_name: str, is_healthy: bool):
        """
        设置适配器健康状态
        
        Args:
            adapter_name: 适配器名称
            is_healthy: 是否健康
        """
        self.registry.set_adapter_health(adapter_name, is_healthy)
    
    def get_routing_stats(self) -> Dict[str, Any]:
        """
        获取路由统计信息
        
        Returns:
            Dict[str, Any]: 统计信息
        """
        return {
            "uptime_seconds": (datetime.now() - self.initialized_at).total_seconds(),
            "total_routes": sum(self.routing_stats.values()),
            "total_failures": sum(self.failure_stats.values()),
            "adapter_stats": {
                adapter: {
                    "routes": self.routing_stats.get(adapter, 0),
                    "failures": self.failure_stats.get(adapter, 0),
                    "success_rate": self._calculate_success_rate(adapter)
                }
                for adapter in self.registry.get_all_adapter_names()
            },
            "registry_stats": self.registry.get_registry_stats(),
            "strategy_count": self.strategy.get_strategy_count(),
            "enabled_strategy_count": self.strategy.get_enabled_strategy_count()
        }
    
    def _calculate_success_rate(self, adapter_name: str) -> float:
        """
        计算适配器成功率
        
        Args:
            adapter_name: 适配器名称
        
        Returns:
            float: 成功率 (0-1)
        """
        routes = self.routing_stats.get(adapter_name, 0)
        failures = self.failure_stats.get(adapter_name, 0)
        
        if routes == 0:
            return 0.0
        
        successes = routes - failures
        return successes / routes if routes > 0 else 0.0
    
    def reset_stats(self):
        """重置统计信息"""
        self.routing_stats.clear()
        self.failure_stats.clear()
        self.initialized_at = datetime.now()
        self.logger.info("路由统计已重置")
    
    def health_check(self) -> Dict[str, Any]:
        """
        执行健康检查
        
        Returns:
            Dict[str, Any]: 健康状态
        """
        healthy_count = self.registry.get_adapter_count(only_healthy=True)
        total_count = self.registry.get_adapter_count(only_healthy=False)
        
        is_healthy = healthy_count > 0
        
        return {
            "healthy": is_healthy,
            "healthy_adapters": healthy_count,
            "total_adapters": total_count,
            "strategy_count": self.strategy.get_strategy_count(),
            "uptime_seconds": (datetime.now() - self.initialized_at).total_seconds()
        }
    
    def __repr__(self) -> str:
        return (
            f"<DataSourceRouter("
            f"adapters={self.registry.get_adapter_count()}, "
            f"strategies={self.strategy.get_strategy_count()}, "
            f"failover={self.enable_auto_failover}"
            f")>"
        )

